package com.xuef.service.impl;

import com.xuef.entity.EsBlog;
import com.xuef.entity.User;
import com.xuef.repository.EsBlogRepository;
import com.xuef.service.EsBlogService;
import com.xuef.service.IUserService;
import com.xuef.vo.TagVO;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.springframework.beans.factory.annotation.Autowired;
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ResultsExtractor;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created by moveb on 2018/5/9.
 */
@Service
public class EsBlogServiceImpl implements EsBlogService {

    @Autowired
    private EsBlogRepository esBlogRepository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private IUserService userService;

    private static final Pageable TOP_5_PAGEABLE = new PageRequest(0, 5);
    private static final String EMPTY_KEYWORD = "";
    @Override
    public void removeEsBlog(String id) {
        esBlogRepository.delete(id);
    }

    @Override
    public EsBlog updateEsBlog(EsBlog esBlog) {
        return esBlogRepository.save(esBlog);
    }

    @Override
    public EsBlog getEsBlogByBlogId(Integer blogId) {
        return esBlogRepository.findByBlogId(blogId);
    }

    @Override
    public Page<EsBlog> listNewestEsBlogs(String keyword, Pageable pageable) {
        return null;
    }

    @Override
    public Page<EsBlog> listHotestEsBlogs(String keyword, Pageable pageable) {
        return null;
    }

    @Override
    public Page<EsBlog> listEsBlogs(Pageable pageable) {
        return null;
    }

    @Override
    public List<EsBlog> listTop5NewestEsBlogs() {
        return null;
    }

    @Override
    public List<EsBlog> listTop5HotestEsBlogs() {
        return null;
    }

    @Override
    public List<TagVO> listTop30Tags(String username) {

        List<TagVO> list = new ArrayList<>();

        //查询条件
        BoolQueryBuilder bqb = QueryBuilders.boolQuery();
        bqb.must(QueryBuilders.termQuery("username", username));
        SearchQuery searchQuery = null;
        if(username == null){
            searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(matchAllQuery())
                    //.withQuery(bqb)
                    .withSearchType(SearchType.QUERY_THEN_FETCH)
                    .withIndices("blog").withTypes("blog")
                    .addAggregation(terms("tags").field("tags").order(Terms.Order.count(false)).size(30))
                    .build();
        }else{
            searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(bqb)
                    .withSearchType(SearchType.QUERY_THEN_FETCH)
                    .withIndices("blog").withTypes("blog")
                    .addAggregation(terms("tags").field("tags").order(Terms.Order.count(false)).size(30))
                    .build();
        }
        // given
        // when
        Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {
            @Override
            public Aggregations extract(SearchResponse response) {
                return response.getAggregations();
            }
        });

        StringTerms modelTerms =  (StringTerms)aggregations.asMap().get("tags");

        Iterator<Bucket> modelBucketIt = modelTerms.getBuckets().iterator();
        while (modelBucketIt.hasNext()) {
            Bucket actiontypeBucket = modelBucketIt.next();

            list.add(new TagVO(actiontypeBucket.getKey().toString(),
                    actiontypeBucket.getDocCount()));
        }
        return list;
    }

    @Override
    public List<User> listTop12Users() {
        return null;
    }

    @Override
    public Page<EsBlog> fullTextSearch(String title, String summary, String content, String tags, Pageable pageable) {
        return esBlogRepository.findDistinctEsBlogByTitleContainingOrSummaryContainingOrContentContainingOrTagsContaining(
                title,
                summary,
                content,
                tags,
                pageable);
    }

    @Override
    public Page<EsBlog> fullTextSearch4OneUser(String username, String title, String summary, String content, String tags, Pageable pageable) {
        return esBlogRepository.findDistinctEsBlogByUsernameContainingOrTitleContainingOrSummaryContainingOrContentContainingOrTagsContaining(
                username,title,
                summary,content,
                tags,pageable
        );
    }
}
